package org.example.thread;


import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.concurrent.*;

/**
 * 说明: 线程池管理器，自带单线程队列
 * Created on 2020/5/1 15:50
 *
 * @author tiancheng
 */
public class ThreadPoolManager {

    public static final int FIND_PATH_THREAD_NUM = 8;

    protected final Logger logger = LogManager.getLogger(ThreadPoolManager.class);

    /**
     * 寻路专用线程组
     */
    private final ExecutorService findPathThreadPool;


    private ThreadPoolManager() {

        findPathThreadPool = new ThreadPoolExecutor(
                FIND_PATH_THREAD_NUM,
                FIND_PATH_THREAD_NUM,
                0L,
                TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>(),
                new ThreadPoolExecutor.AbortPolicy());
    }

    /**
     * 是否是合服模式
     */
    private boolean merge;

    /**
     * 用枚举来实现单例
     */
    private enum Singleton {
        INSTANCE;
        ThreadPoolManager processor;

        Singleton() {
            this.processor = new ThreadPoolManager();
        }

        ThreadPoolManager getProcessor() {
            return processor;
        }
    }

    /**
     * 获取实例对象
     *
     * @return
     */
    public static ThreadPoolManager getInstance() {
        return Singleton.INSTANCE.getProcessor();
    }

    /**
     * 停止所有线程
     */
    public void stop() {
        try {
            waitForCompletion(findPathThreadPool, 5);
        } catch (InterruptedException e) {
            findPathThreadPool.shutdown();

        }
    }

    /**
     * 添加执行线程
     *
     * @param task
     * @return
     */
    public Future<?> addFindPathTask(ThreadTask task) {
        if (merge) {
            logger.warn("当前是合服模式!!不要添加异步任务");
        }
        return findPathThreadPool.submit(task);
    }

    public boolean isMerge() {
        return merge;
    }

    public void setMerge(boolean merge) {
        this.merge = merge;
    }

    /**
     * 等待直到所有任务在给定线程池中完成，或者超时。
     *
     * @param executorService 要等待的线程池
     * @param timeoutSeconds  超时时间，以秒为单位
     * @return 如果所有任务在超时前完成，则返回true；否则返回false
     * @throws InterruptedException 如果当前线程在等待过程中被中断
     */
    public boolean waitForCompletion(ExecutorService executorService, long timeoutSeconds) throws InterruptedException {
        executorService.shutdown(); // 发起关闭请求，不会立即停止线程池，已提交的任务会正常执行
        try {
            // 等待直到所有任务完成或超时
            return executorService.awaitTermination(timeoutSeconds, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            // 如果当前线程在等待过程中被中断，则减少中断状态（恢复中断状态）并抛出异常
            Thread.currentThread().interrupt();
            throw e;
        }
    }

}
